package cn.mill.core.modem;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.mill.common.Context;
import cn.mill.common.Tag;
import cn.mill.common.annotation.Property;
import cn.mill.common.annotation.TagAll;
import cn.mill.common.data.Item;
import cn.mill.common.data.ItemArray;
import cn.mill.core.MillConfig;
import cn.mill.core.utils.NormUtil;

public class JavaBeanSpell implements ObjectSpell, FieldSpell {
	private static final Logger logger = LoggerFactory.getLogger(JavaBeanSpell.class);
	
	public static JavaBeanSpell INSTANCE = new JavaBeanSpell();
	
	@Override
	public <T> T builder(Type type, Item item) {
		if (item != null && item.getValue() instanceof ItemArray) {
			return this.builder(type, (ItemArray) item.getValue());
		}
		return null;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public <T> T builder(Type type, ItemArray itemArray) {
		if ((itemArray == null || itemArray.getSize() <= 0) && NormUtil.getActualType(type) == null) {
			/**
			 * 没有数据返回 null 对象 如果 数据 属性 数组为空 并且 目标 对象
			 * 不是泛型则返回null，如果目标对象是泛型的，则返回一个对象
			 */
			return null;
		}
		Object o = NormUtil.createJavaObject(type);
		if (o != null && itemArray != null && itemArray.getSize() > 0) {
			Field[] fs = NormUtil.getJavaBeanField(o);
			itemArray.sort();// 数据排序，便于二分查找
			for (Field f : fs) {// 静态 字段除外！
				if (!Modifier.isStatic((f.getModifiers()))) {
					f.setAccessible(true);
					Property property = f.getAnnotation(Property.class);
					String name = property == null ? f.getName().toUpperCase() : (NormUtil.isEmpty(property.name()) ? property.value() : property.name());
					String synonym = property == null ? "" : property.synonym();
					Item item = NormUtil.leapfrogSearch(name, synonym, itemArray);
					// itemArray.search(name, synonym);
					if (item != null) {
						item.setProperty(property);
						item.setType(f.getGenericType());
						Type t = NormUtil.getType(type, f.getGenericType());
						FieldSpell fieldSpell = (FieldSpell) MillConfig.getBuilder(t);
						Object value = fieldSpell.builder(t, item);
						try {
							f.set(o, value);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				}
			}
		}
		return (T) o;
	}
	
	@Override
	public ItemArray resolver(Context context, Type type, Object object) {
		if (object == null) {
			return new ItemArray(1);
		}
		Field[] fs = NormUtil.getJavaBeanField(object);
		TagAll tag = object.getClass().getAnnotation(TagAll.class);
		if (fs != null && fs.length > 0) {
			ItemArray resault = new ItemArray(fs.length * 4 / 5);
			for (Field f : fs) {// 静态 字段除外！
				if (!Modifier.isStatic((f.getModifiers()))) {
					f.setAccessible(true);
					Property property = f.getAnnotation(Property.class);
					String name = property == null ? f.getName() : (NormUtil.isEmpty(property.name()) ? property.value() : property.name());
					Item item = null;
					FieldSpell resolver = (FieldSpell) MillConfig.getResolver(f.getType());
					try {
						Object fobject = f.get(object);
						if (fobject != null && property != null) {
							item = resolver.resolver(context, name, f.getType(), fobject);
							item.setProperty(property);
							if (item != null) {
								if (!Tag.BODY.equals(property.tag()) || !Tag.BODY.equals(tag)) {
									context.addAttachments(item.getName(), item);
								}
								resault.addItem(item);
							}
						}
					} catch (Exception e) {
						logger.error(" JavaBeanResolver get Java bean filed error->", e);
					}
				}
			}
			resault.sort();
			return resault;
		}
		return new ItemArray(1);
	}
	
	/** 这里用不到 . Java bean 只能放在 ItemArray **/
	@Override
	public Item resolver(Context context, String name, Type type, Object object) {
		
		return null;
	}
}
